package analisis;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import utils.OS;

/**
 * @file GoGanpa.java
 * @author Juan
 * @date 04-Marzo-2014
 */
public class GoGanpa {

    /**
     * Método que genera y ejecuta un script en R que crea una red de genes a
     * partir de los genes del fichero de entrada
     *
     * @param ficheroLista lista de genes
     * @param ont ontologia de GO
     * @param measure medida para calcular similaridades semanticas entre genes
     * @param org organismo
     * @param combine métodos para la combinación de las puntuaciones de
     * similitud semántica de múltiples GO términos asociados con la proteína o
     * múltiples proteínas asociadas con el grupo de proteínas.
     * @param rho Umbral a partir del cual se añade una arista de pares de
     * genes.
     * @param sesion ruta de la carpeta temporal del usuario
     * @param nombre de la red
     * @throws java.io.IOException
     * @throws java.lang.InterruptedException
     */
    public static void generarScript(String ficheroLista, String ont, String measure,
            String org, String combine, String rho, String sesion, String nombre) throws IOException, InterruptedException {
        String separator = OS.getDirectorySeparator();
        String raiz = OS.getR();
        String barras = OS.getDoubleDirectorySeparator();
        String genes = crearGenes(ficheroLista);
        File directorio = new File(sesion);

        //int pos = sesion.lastIndexOf(separator);
        //String r = sesion.substring(0, pos);
        //pos = r.lastIndexOf(separator);
        //r = r.substring(0, pos);

        if (directorio.mkdir()) {
        }

        File script = new File(sesion + separator + "script.R");
        script.createNewFile();

        File salida = new File(sesion + separator + nombre + ".sif");
        salida.createNewFile();

        PrintWriter pwScript;
        try (FileWriter scriptW = new FileWriter(sesion + separator + "script.R")) {
            pwScript = new PrintWriter(scriptW);
            pwScript.flush();
            pwScript.println("library(GOSemSim)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(WGCNA)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GANPAdata)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GANPA)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GOGANPA)");
            pwScript.flush();
            //Crear una variable en r con la lista de genes
            pwScript.flush();
            pwScript.println("genes <-c(" + genes + ")");
            pwScript.flush();
            //LLamada a GoSemSim, para crear la matriz de similitud
            pwScript.flush();
            pwScript.println("x <- mgeneSim(genes, ont = \"" + ont + "\", organism = \"" + org + "\""
                    + ", drop=NULL, verbose = FALSE, measure =\"" + measure + "\", combine=\"" + combine + "\")");
            pwScript.flush();
            //Llamada a GOGANPA para crear la red
            pwScript.flush();
            pwScript.println("gNET <- getGNET(x, rho = " + rho + ")");
            pwScript.flush();
            String sesionR = "";
            String[] linea2 = sesion.split(barras);
            for (int i = 0; i < linea2.length; i++) {
                if (i < linea2.length - 1) {
                    sesionR += linea2[i] + barras;

                } else {
                    sesionR += linea2[i];
                }

            }   //Pasar el resultado a un fichero
            pwScript.flush();
            pwScript.print("for (i in 1:length(gNET)) write(paste(names(gNET[i]),gNET[[i]],sep=\" relation \"),\"" + sesionR + barras + nombre + ".sif\",append=TRUE)");
            pwScript.flush();
        }
        pwScript.close();

        /*Se pasa por parametro la ruta donde se encuentra la variable de r
         y el archivo .r a ejecutar*/
        Process p = Runtime.getRuntime().exec(raiz + sesion + separator + "script.R");

        p.waitFor();

    }

    /**
     * Método que genera y ejecuta un script en R que crea una red de genes a
     * partir de los genes de un termino GO
     *
     * @param ficheroLista lista de genes
     * @param ont ontologia de GO
     * @param measure medida para calcular similaridades semanticas entre genes
     * @param org organismo
     * @param combine métodos para la combinación de las puntuaciones de
     * similitud semántica de múltiples GO términos asociados con la proteína o
     * múltiples proteínas asociadas con el grupo de proteínas.
     * @param rho Umbral a partir del cual se añade una arista de pares de
     * genes.
     * @param sesion ruta de la carpeta temporal del usuario
     * @param termino nombre del termino
     * @throws java.io.IOException
     * @throws java.lang.InterruptedException
     */
    public static void generarScript(List<String> ficheroLista, String ont, String measure,
            String org, String combine, String rho, String sesion, String termino) throws IOException, InterruptedException {

        if (termino.equals("")) {
            termino = ont;
        } else {
            termino = termino.substring(3);
        }
        String separator = OS.getDirectorySeparator();
        String raiz = OS.getR();
        String barras = OS.getDoubleDirectorySeparator();
        String genes = crearGenes(ficheroLista);
        File directorio = new File(sesion);

        //int pos = sesion.lastIndexOf(separator);
        //String r = sesion.substring(0, pos);
        //pos = r.lastIndexOf(separator);
        //r = r.substring(0, pos);

        if (directorio.mkdir()) {
        }

        File script = new File(sesion + separator + "script.R");
        script.createNewFile();

        File salida = new File(sesion + separator + termino + ".sif");
        salida.createNewFile();

        PrintWriter pwScript;
        try (FileWriter scriptW = new FileWriter(sesion + separator + "script.R")) {
            pwScript = new PrintWriter(scriptW);
            pwScript.flush();
            pwScript.println("library(GOSemSim)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(WGCNA)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GANPAdata)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GANPA)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(GOGANPA)");
            pwScript.flush();
            //Crear una variable en r con la lista de genes
            pwScript.flush();
            pwScript.println("genes <-c(" + genes + ")");
            pwScript.flush();
            //LLamada a GoSemSim, para crear la matriz de similitud
            pwScript.flush();
            pwScript.println("x <- mgeneSim(genes, ont = \"" + ont + "\", organism = \"" + org + "\""
                    + ", drop=NULL, verbose = FALSE, measure =\"" + measure + "\", combine=\"" + combine + "\")");
            pwScript.flush();
            //Llamada a GOGANPA para crear la red
            pwScript.flush();
            pwScript.println("gNET <- getGNET(x, rho = " + rho + ")");
            pwScript.flush();
            String sesionR = "";
            String[] linea2 = sesion.split(barras);
            for (int i = 0; i < linea2.length; i++) {
                if (i < linea2.length - 1) {
                    sesionR += linea2[i] + barras;

                } else {
                    sesionR += linea2[i];
                }

            }   //Pasar el resultado a un fichero
            pwScript.flush();
            pwScript.print("for (i in 1:length(gNET)) write(paste(names(gNET[i]),gNET[[i]],sep=\" relation \"),\"" + sesionR + barras + termino + ".sif\",append=TRUE)");
            pwScript.flush();
        }
        pwScript.close();

        /*Se pasa por parametro la ruta donde se encuentra la variable de r
         y el archivo .r a ejecutar*/
        Process p = Runtime.getRuntime().exec(raiz + sesion + separator + "script.R");

        p.waitFor();

    }

    /**
     * Método que devuelve un String con lista de genes del fichero de entrada
     * con el formato adecuado para el script de R
     *
     * @param archivo ruta del archivo donde estan los genes
     * @return listaGenes
     */
    private static String crearGenes(String archivo) {
        String listaGenes = "";

        FileReader fre = null;
        BufferedReader bre = null;

        try {
            // Apertura del fichero y creacion de BufferedReader para poder
            // hacer una lectura comoda (disponer del metodo readLine()).

            fre = new FileReader(archivo);
            bre = new BufferedReader(fre);

            // Lectura del fichero
            int cont = 0;
            String linea;
            //Se le da el formato necesario para el script R
            while ((linea = bre.readLine()) != null) {
                if (cont != 0) {
                    listaGenes += ",";
                }
                listaGenes += "\"" + linea + "\"";

                cont++;

            }
            listaGenes = listaGenes.substring(0, listaGenes.length());

        } catch (IOException e) {

        } finally {
            // En el finally cerramos el fichero, para asegurarnos
            // que se cierra tanto si todo va bien como si salta 
            // una excepcion.
            try {
                if (null != fre) {
                    fre.close();
                }
            } catch (IOException e2) {

            }
        }
        return listaGenes;
    }

    /**
     * Método que devuelve un String con lista de genes del fichero de entrada
     * con el formato adecuado para el script de R
     *
     * @param lista de genes
     * @return listaGenes
     */
    private static String crearGenes(List<String> lista) {
        String listaGenes = "";
        for (int i = 0; i < lista.size(); i++) {
            if (i != 0) {
                listaGenes += ",";
            }
            listaGenes += "\"" + lista.get(i) + "\"";

        }
        listaGenes = listaGenes.substring(0, listaGenes.length());
        return listaGenes;
    }

}
